package cn.virens.common.boot.dubbo.filter.attachment;

import cn.virens.common.util.core.objcet.ObjectUtil;
import cn.virens.common.util.exception.APIException;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.dromara.hutool.core.convert.ConvertUtil;

import java.util.*;
import java.util.Map.Entry;

public class AttachmentUtils extends InheritableThreadLocal<Map<String, Object>> {
    private static final Map<String, Object> EMPTY = Collections.emptyMap();

    private static final AttachmentUtils LOCAL = new AttachmentUtils();

    @Override
    protected Map<String, Object> childValue(Map<String, Object> parentValue) {
        return parentValue != null ? new HashMap<>(parentValue) : null;
    }

    /**
     * 将请求中的参数全部存入当前线程变量中，并放行对应操作
     */
    protected static Result invoke(Invoker<?> invoker, Invocation invocation) {
        if (invocation != null && invocation.getObjectAttachments() != null) {
            LOCAL.set(invocation.getObjectAttachments());
        }

        return invoker.invoke(invocation);
    }

    /**
     * 添加RPC变量参数
     */
    public Object addAttachment(String key, Object value) throws APIException {
        return getAttachments().put(key, ObjectUtil.toString(value));
    }

    /**
     * 获取当前参数集
     */
    public static Map<String, Object> getAttachments() throws APIException {
        return Objects.requireNonNullElse(LOCAL.get(), EMPTY);
    }

    /**
     * 获取一个属性
     */
    public static Boolean getAttachmentBool(String key) throws APIException {
        return ConvertUtil.toBoolean(getAttachment(key), null);
    }

    /**
     * 获取一个属性
     */
    public static Integer getAttachmentInt(String key) throws APIException {
        return ConvertUtil.toInt(getAttachment(key), null);
    }

    /**
     * 获取一个属性
     */
    public static String getAttachmentStr(String key) throws APIException {
        return ConvertUtil.toStr(getAttachment(key), null);
    }

    /**
     * 获取一个属性
     */
    public static Object getAttachment(String key) throws APIException {
        return getAttachments().get(key);
    }

    /**
     * 遍历当前缓存变量
     */
    protected static Set<Entry<String, Object>> entrySet() {
        Map<String, Object> map = LOCAL.get();
        if (map != null && !map.isEmpty()) {
            return map.entrySet();
        } else {
            return Set.of();
        }
    }
}
